/*! 
 * Header file for the particle class.
 *
 * \author Devis Rossini
 * \date 25 May 2012
 */ 
#ifndef PHXPARTICLE_H_INCLUDE_GUARD
#define PHXPARTICLE_H_INCLUDE_GUARD

#include "PhxCore.h"

namespace phx 
{
    /*!
	 * Particle class represent a point-link body.
     */
    class Particle
    {
    protected:

		#pragma region Characteristic data

        /*!
         * \name Characteristic data
		 *
         * Characteristics are properties of the particle
         * independent of its current kinematic situation. This
         * includes mass, moment of inertia and damping
         * properties. Two identical particles will have the same
         * values for their characteristics.
         *
         */
        /*@{*/

        /*!
         * Holds the inverse of the mass of the particle.
         */
        real mInverseMass;

        /*!
         * Holds the amount of damping applied to linear
         * motion.
         */
        real mDamping;

		/*@}*/

		#pragma endregion 

		#pragma region Kinematic state

		/*!
         * \name Kinematic state
         *
		 * Kinematic description of the particle.
         */
        /*@{*/

        /*!
         * Holds the linear position of the particle in
         * world space.
         */
        Vector3 mPosition;

        /*!
         * Holds the linear velocity of the particle in
         * world space.
         */
        Vector3 mVelocity;

        /*@}*/

		#pragma endregion

		#pragma region Force and acceleration

        /*!
         * \name Force Accumulators
         *
         * These data members store the current force and
         * global linear acceleration of the particle.
         */

        /*@{*/

        /*!
         * Holds the accumulated force to be applied at the next
         * simulation iteration only. This value is zeroed at each
         * integration step.
         */
        Vector3 mForceAccumulator;

        /*!
         * Holds the acceleration of the particle.  This value
         * can be used to set acceleration due to gravity (its primary
         * use), or any other constant acceleration.
         */
        Vector3 mAcceleration;

        /*@}*/

		#pragma endregion

    public:

		#pragma region Constructors

        /*!
         * \name Constructor and Destructor
         *
         * There are no data members in the particle class that are
         * created on the heap. So all data storage is handled
         * automatically.
         */
        /*@{*/
        /*@}*/

		#pragma endregion

		#pragma region Integration functions

        /*!
         * \name Integration functions
         *
         * These functions are used to simulate the particle's
         * motion over time. 
		 *
         * Currently the only integration function provided is the
         * first order Newton Euler method.
         */
        /*@{*/

        /*!
         * Integrates the particle forward in time by the given amount.
         * This function uses a Newton-Euler integration method, which is a
         * linear approximation to the correct integral. For this reason it
         * may be inaccurate in some cases.
         */
        void Integrate(real duration);

        /*@}*/

		#pragma endregion

		#pragma region Accessor functions

        /*!
         * \name Accessor functions
         *
         * These functions provide access to the particle's
         * characteristics or kinematic state.
         */
        /*@{*/

        /*!
         * Sets the mass of the particle.
         */
        void SetMass(const real mass);

        /*!
         * Gets the mass of the particle.
		 */
        real GetMass() const;

        /*!
         * Sets the inverse mass of the particle.
         */
        void SetInverseMass(const real inverseMass);

        /*!
         * Gets the inverse mass of the particle.
         */
        real GetInverseMass() const;

        /*!
         * Returns true if the mass of the particle is not-infinite.
         */
        bool HasFiniteMass() const;

        /*!
         * Sets the damping of the particle.
         */
        void SetDamping(const real damping);

        /*!
         * Gets the current damping value.
         */
        real GetDamping() const;

        /*!
         * Sets the position of the particle.
         */
        void SetPosition(const Vector3& position);

        /*!
         * Sets the position of the particle by component.
         */
        void SetPosition(const real x, const real y, const real z);

        /*!
         * Fills the given vector with the position of the particle.
         */
        void GetPosition(Vector3* position) const;

        /*!
         * Gets the position of the particle.
         */
        Vector3 GetPosition() const;

        /*!
         * Sets the velocity of the particle.
         */
        void SetVelocity(const Vector3& velocity);

        /*!
         * Sets the velocity of the particle by component.
         */
        void SetVelocity(const real x, const real y, const real z);

        /*!
         * Fills the given vector with the velocity of the particle.
         */
        void GetVelocity(Vector3* velocity) const;

        /*!
         * Gets the velocity of the particle.
         */
        Vector3 GetVelocity() const;

        /*!
         * Sets the constant acceleration of the particle.
         */
        void SetAcceleration(const Vector3& acceleration);

        /*!
         * Sets the constant acceleration of the particle by component.
         */
        void SetAcceleration(const real x, const real y, const real z);

        /*!
         * Fills the given vector with the acceleration of the particle.
         */
        void GetAcceleration(Vector3* acceleration) const;

        /*!
         * Gets the acceleration of the particle.
         */
        Vector3 GetAcceleration() const;

        /*@}*/

		#pragma endregion

		#pragma region Force set-up functions

        /*!
         * \name Force set-up functions
         *
         * These functions set up forces to apply to the
         * particle.
         */
        /*@{*/

        /*!
         * Clears the forces applied to the particle. This will be
         * called automatically after each integration step.
         */
        void ClearAccumulator();

        /*!
         * Adds the given force to the particle, to be applied at the
         */
        void AddForce(const Vector3& force);
		
		/*@}*/

		#pragma endregion
    };
}

#endif // PHXPARTICLE_H_INCLUDE_GUARD